#ifndef __GLF_CORE_TYPES_H_INCLUDED__
#define __GLF_CORE_TYPES_H_INCLUDED__

#include <glf/config.h>

namespace glf {

typedef unsigned long	ulong;
typedef unsigned int	uint;
typedef unsigned short	ushort;
typedef unsigned char	uchar;

#if !defined(PTRDIF_T_DEFINED) && (defined(SN_TARGET_PS3) || defined(PLATFORM_PLAYBOOK) || defined(NN_PLATFORM_CTR) /* 3DS */)
typedef int ptrdiff_t;
#define PTRDIF_T_DEFINED
#endif

template<typename T> struct rect;
template<typename T> struct point;
template<typename T> struct size;

template<typename T> struct Rect;
template<typename T> struct Point;
template<typename T> struct Size;


typedef rect<int> recti;
typedef point<int> pointi;
typedef size<int> sizei;

typedef rect<float> rectf;
typedef point<float> pointf;
typedef size<float> sizef;


typedef Rect<int> Recti;
typedef Point<int> Pointi;
typedef Size<int> Sizei;

typedef Rect<float> Rectf;
typedef Point<float> Pointf;
typedef Size<float> Sizef;


template<typename T>
struct point 
{
	T x,y;
};

template<typename T>
struct size
{
	T w,h;
};

template<typename T>
struct rect
{
	/*
	union {
		struct {
		point<T> topLeft;
		point<T> bottomRight;
		};
		struct {
			T left, top, right, bottom;
		};
	};
	*/

	//point<
	T left, top, right, bottom;
};

template<typename T>
struct Point : public point<T>
{
	// create an uninitialized point
	Point<T>();
	// create from two integers
	Point<T>(T x, T y);
	// create from another point
	Point<T>(const point<T>& p);
	// create from a size
	Point<T>(const size<T>& s);


// Operations

// translate the point
	void Offset(T xOffset, T yOffset);
	void Offset(const point<T>& point);
	void Offset(const size<T>& size);
	void Set(T X, T Y);
	void Set(const Point<T>& p);

	bool operator==(const point<T>& point) const;
	bool operator!=(const point<T>& point) const;
	void operator+=(const size<T>& size);
	void operator-=(const size<T>& size);
	void operator+=(const point<T>& point);
	void operator-=(const point<T>& point);

// Operators returning Point values
	Point<T> operator+(const size<T>& size) const;
	Point<T> operator-(const size<T>& size) const;
	Point<T> operator-() const;
	Point<T> operator+(const point<T>& point) const;

// Operators returning Size values
	Size<T> operator-(const point<T>& point) const;

// Operators returning Rect values
	Rect<T> operator+(const rect<T>& lpRect) const;
	Rect<T> operator-(const rect<T>& lpRect) const;

// Cast operators
	operator T *();
	operator const T *() const;
};

template<typename T>
struct Size : public size<T>
{
	Size();
	// create from two integers
	Size(T x, T y);
	// create from another size
	Size(const size<T>& initSize);
	// create from a point
	Size(const point<T>& p);

// Operations
	bool operator==(const size<T>& size) const;
	bool operator!=(const size<T>& size) const;
	void operator+=(const size<T>& size);
	void operator-=(const size<T>& size);
	void SetSize(T w, T h);

// Operators returning Size values
	Size operator+(const size<T>& size) const;
	Size operator-(const size<T>& size) const;
	Size operator-() const;

// Operators returning Point values
	Point<T> operator+(const point<T>& point) const;
	Point<T> operator-(const point<T>& point) const;

// Operators returning Rect values
	Rect<T> operator+(const rect<T>& r) const;
	Rect<T> operator-(const rect<T>& r) const;
};

template<typename T>	
struct Rect : public rect<T>
{
	Rect();
	// from left, top, right, and bottom
	Rect(T l, T t, T r, T b);
	// copy constructor
	Rect(const rect<T>& srRect);
	// from a pointer to another rect
	//Rect(LPRect lpSrRect);
	// from a point and size
	Rect(const point<T>& point, const size<T>& size);
	// from two points
	Rect(const point<T>& topLeft, const point<T>& bottomRight);

// Attributes (in addition to rect members)

	// retrieves the width
	T Width() const;
	// returns the height
	T Height() const;
	// returns the size
	struct Size<T> Size() const;
	// reference to the top-left point
	Point<T>& TopLeft();
	// reference to the bottom-right point
	Point<T>& BottomRight();
	// const reference to the top-left point
	const Point<T>& TopLeft() const;
	// const reference to the bottom-right point
	const Point<T>& BottomRight() const;
	// the geometric center point of the rectangle
	Point<T> CenterPoint() const;
	// swap the left and right
	void SwapLeftRight();
	//static void SwapLeftRight(LPRECT lpRect);

	// convert between Rect and LPRECT/LPRect (no need for &)
	operator rect<T>&();
	//operator Rect<T>&() const;

	// returns true if rectangle has no area
	bool IsRectEmpty() const;
	// returns true if rectangle is at (0,0) and has no area
	bool IsRectNull() const;
	// returns true if point is within rectangle
	bool PtInRect(const point<T>& point) const;

// Operations

	// set rectangle from left, top, right, and bottom
	void SetRect(T x1, T y1, T x2, T y2);
	void SetRect(const point<T>& topLeft, const point<T>& bottomRight);
	// empty the rectangle
	void SetRectEmpty();
	// copy from another rectangle
	void CopyRect(const rect<T>& r);
	// true if exactly the same as another rectangle
	bool EqualRect(const rect<T>& r) const;

	// Inflate rectangle's width and height by
	// x units to the left and right ends of the rectangle
	// and y units to the top and bottom.
	void InflateRect(T x, T y);
	// Inflate rectangle's width and height by
	// size.w units to the left and right ends of the rectangle
	// and size.h units to the top and bottom.
	void InflateRect(const size<T>& size);
	// Inflate rectangle's width and height by moving individual sides.
	// Left side is moved to the left, right side is moved to the right,
	// top is moved up and bottom is moved down.
	void InflateRect(const rect<T>& r);
	void InflateRect(T l, T t, T r, T b);

	// deflate the rectangle's width and height without
	// moving its top or left
	void DeflateRect(T x, T y);
	void DeflateRect(const size<T>& size);
	void DeflateRect(const rect<T>& r);
	void DeflateRect(T l, T t, T r, T b);

	// translate the rectangle by moving its top and left
	void OffsetRect(T x, T y);
	void OffsetRect(const size<T>& size);
	void OffsetRect(const point<T>& point);
	void NormalizeRect();

	// absolute position of rectangle
	void MoveToY(T y);
	void MoveToX(T x);
	void MoveToXY(T x, T y);
	void MoveToXY(const point<T>& point);

	// set this rectangle to intersection of two others
	bool IntersectRect(const rect<T>& r1, const rect<T>& r2);

	// set this rectangle to bounding union of two others
	bool UnionRect(const rect<T>& r1, const rect<T>& r2);

	// set this rectangle to minimum of two others
	bool SubtractRect(const rect<T>& r1, const rect<T>& r2);

// Additional Operations
	void operator=(const rect<T>& srRect);
	bool operator==(const rect<T>& rect) const;
	bool operator!=(const rect<T>& rect) const;
	void operator+=(const point<T>& point);
	void operator+=(const size<T>& size);
	void operator+=(const rect<T>& r);
	void operator-=(const point<T>& point);
	void operator-=(const size<T>& size);
	void operator-=(const rect<T>& r);
	void operator&=(const rect<T>& r);
	void operator|=(const rect<T>& r);

// Operators returning Rect values
	Rect operator+(const point<T>& point) const;
	Rect operator-(const point<T>& point) const;
	Rect operator+(const rect<T>& r) const;
	Rect operator+(const size<T>& size) const;
	Rect operator-(const size<T>& size) const;
	Rect operator-(const rect<T>& r) const;
	Rect operator&(const rect<T>& rect2) const;
	Rect operator|(const rect<T>& rect2) const;
	Rect Mul(T nMultiplier) const;
	Rect MulDiv(T nMultiplier, T nDivisor=T(1)) const;

	//for generic backward compatibility
	T CenterX() const {
		return this->left + this->right / 2;
	}
	T CenterY() const {
		return this->top + this->bottom / 2;
	}

	bool IsPointInside(T x, T y) const {
		return x >= this->left  && x <= this->right && y >= this->top && y <= this->bottom;
	}

	void Move(T x, T y)
	{
		this->left += x;	
		this->right += x;

		this->bottom += y;
		this->top += y;
	}


};

#define GLF_TYPES_INLINE inline

//TODO implement helper functions

template<typename T>
GLF_TYPES_INLINE void CopyRect(rect<T>& dst, const rect<T>& src) 
{
	dst = src;
}

template<typename T>
GLF_TYPES_INLINE void SwapLeftRight(rect<T>& r) 
{
	T tmp = r.left;
	r.left = r.right;
	r.right = tmp;
}

template<typename T>
GLF_TYPES_INLINE bool IsRectEmpty(const rect<T>& r) 
{
	return r.left >= r.right || r.top >= r.bottom;
}

template<typename T>
GLF_TYPES_INLINE bool PtInRect(const rect<T>& r, const point<T>& p) 
{
	return false;
}

template<typename T>
GLF_TYPES_INLINE void SetRect(rect<T>& r, T x1, T y1, T x2, T y2) 
{
	r.left = x1;
	r.right = x2;
	r.top = y1;
	r.bottom = y2;
}

template<typename T>
GLF_TYPES_INLINE void SetRectEmpty(rect<T>& r) 
{
	r.left = r.right = r.top = r.bottom = T(0);
}

template<typename T>
GLF_TYPES_INLINE bool EqualRect(const rect<T>& r1, const rect<T>& r2) 
{
	return r1.left == r2.left && r1.right == r2.right && r1.top == r2.top && r1.bottom == r2.bottom;
}

template<typename T>
GLF_TYPES_INLINE bool SubtractRect(rect<T>& r, const rect<T>& r1, const rect<T>& r2)
{
	return false;
}

template<typename T>
GLF_TYPES_INLINE bool UnionRect(rect<T>& r, const rect<T>& r1, const rect<T>& r2)
{
	return false;
}

template<typename T>
GLF_TYPES_INLINE bool IntersectRect(rect<T>& r, const rect<T>& r1, const rect<T>& r2)
{
	return false;
}

template<typename T>
GLF_TYPES_INLINE void InflateRect(rect<T>& r, T x, T y)
{
	r.right += x;		
	r.bottom += y;
}

template<typename T>
GLF_TYPES_INLINE void Deflate(rect<T>& r, T x, T y)
{
	r.right -= x;		
	r.bottom -= y;
}

template<typename T>
GLF_TYPES_INLINE void OffsetRect(rect<T>& r, T x, T y)
{

}



template<typename T>
GLF_TYPES_INLINE Size<T>::Size()
{ 
	// random filled 
}

template<typename T>
GLF_TYPES_INLINE Size<T>::Size(T initw, T inith)
{ 
	this->w = initw;
	this->h = inith;
}

template<typename T>
GLF_TYPES_INLINE Size<T>::Size(const size<T>& initSize)
{ 
	this->w = initSize.w;
	this->h = initSize.h;
	//*(size*)this = initSize;
}

template<typename T>
GLF_TYPES_INLINE Size<T>::Size(const point<T>& initPt)
{ 
	this->w = initPt.x;
	this->h = initPt.y;	
	//*(point*)this = initPt;
}

template<typename T>
GLF_TYPES_INLINE bool Size<T>::operator==(const size<T>& size) const
{ 
	return (this->w == size.w && this->h == size.h);
}

template<typename T>
GLF_TYPES_INLINE bool Size<T>::operator!=(const size<T>& size) const
{ 
	return (this->w != size.w || this->h != size.h);
}

template<typename T>
GLF_TYPES_INLINE void Size<T>::operator+=(const size<T>& size)
{ 
	this->w += size.w;
	this->h += size.h;
}

template<typename T>
GLF_TYPES_INLINE void Size<T>::operator-=(const size<T>& size)
{
	this->w -= size.w;
	this->h -= size.h;
}

template<typename T>
GLF_TYPES_INLINE void Size<T>::SetSize(T w, T h)
{ 
	this->w = w;
	this->h = h;
	}	

template<typename T>
GLF_TYPES_INLINE Size<T> Size<T>::operator+(const size<T>& size) const
{
	return Size<T>(this->w + size.w, this->h + size.h);
}

template<typename T>
GLF_TYPES_INLINE Size<T> Size<T>::operator-(const size<T>& size) const
{
	return Size<T>(this->w - size.w, this->h - size.h);
}

template<typename T>
GLF_TYPES_INLINE Size<T> Size<T>::operator-() const
{
	return Size<T>(-this->w, -this->h);
}

template<typename T>
GLF_TYPES_INLINE Point<T> Size<T>::operator+(const point<T>& point) const
{
	return Point<T>(this->w + point.x, this->h + point.y);
}

template<typename T>
GLF_TYPES_INLINE Point<T> Size<T>::operator-(const point<T>& point) const
{
	return Point<T>(this->w - point.x, this->h - point.y);
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Size<T>::operator+(const rect<T>& r) const
{
	return Rect<T>(r) + *this;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Size<T>::operator-(const rect<T>& r) const
{
	return Rect<T>(r) - *this;
}

// Point
template<typename T>
GLF_TYPES_INLINE Point<T>::Point()
{ 
	// random filled 
}

template<typename T>
GLF_TYPES_INLINE Point<T>::Point(T initX, T initY)
{
	this->x = initX;
	this->y = initY;
}

template<typename T>
GLF_TYPES_INLINE Point<T>::Point(const point<T>& initPt)
{
	*(Point<T>*)this = initPt;
}

template<typename T>
GLF_TYPES_INLINE Point<T>::Point(const size<T>& initSize)
{ 
	this->x = initSize.w;
	this->y = initSize.h;
	//*(size*)this = initSize;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::Offset(T xOffset, T yOffset)
{
	this->x += xOffset;
	this->y += yOffset;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::Offset(const point<T>& point)
{
	this->x += point.x;
	this->y += point.y;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::Offset(const size<T>& size)
{
	this->x += size.w;
	this->y += size.h;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::Set(T X, T Y)
{
	this->x = X;
	this->y = Y;
}

template<typename T>
void Point<T>::Set(const Point<T>& p) {
	this->x = p.x;
	this->y = p.y;
}

template<typename T>
GLF_TYPES_INLINE bool Point<T>::operator==(const point<T>& point) const
{
	return (this->x == point.x && this->y == point.y);
}

template<typename T>
GLF_TYPES_INLINE bool Point<T>::operator!=(const point<T>& point) const
{
	return (this->x != point.x || this->y != point.y);
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::operator+=(const size<T>& size)
{
	this->x += size.w;
	this->y += size.h;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::operator-=(const size<T>& size)
{
	this->x -= size.w;
	this->y -= size.h;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::operator+=(const point<T>& point)
{
	this->x += point.x;
	this->y += point.y;
}

template<typename T>
GLF_TYPES_INLINE void Point<T>::operator-=(const point<T>& point)
{
	this->x -= point.x;
	this->y -= point.y;
}

template<typename T>
GLF_TYPES_INLINE Point<T> Point<T>::operator+(const size<T>& size) const
{
	return Point<T>(this->x + size.w, this->y + size.h);
}

template<typename T>
GLF_TYPES_INLINE Point<T> Point<T>::operator-(const size<T>& size) const
{
	return Point<T>(this->x - size.w, this->y - size.h);
}

template<typename T>
GLF_TYPES_INLINE Point<T> Point<T>::operator-() const
{
	return Point<T>(-this->x, -this->y);
}

template<typename T>
GLF_TYPES_INLINE Point<T> Point<T>::operator+(const point<T>& point) const
{
	return Point<T>(this->x + point.x, this->y + point.y);
}

template<typename T>
GLF_TYPES_INLINE Size<T> Point<T>::operator-(const point<T>& point) const
{
	return Size<T>(this->x - point.x, this->y - point.y);
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Point<T>::operator+(const rect<T>& r) const
{
	return Rect<T>(r) + *this;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Point<T>::operator-(const rect<T>& r) const
{
	return Rect<T>(r) - *this;
}
	
template<typename T>
GLF_TYPES_INLINE Point<T>::operator T *()
{
	return &this->x;
}

template<typename T>
GLF_TYPES_INLINE Point<T>::operator const T *() const
{
	return &this->x;
}
	
template<typename T>
GLF_TYPES_INLINE Rect<T>::Rect()
{
	/* random filled */ 
}

template<typename T>
GLF_TYPES_INLINE Rect<T>::Rect(T l, T t, T r, T b)
{
	this->left = l;
	this->top = t;
	this->right = r;
	this->bottom = b;
}

template<typename T>
GLF_TYPES_INLINE Rect<T>::Rect(const rect<T>& r)
{
    glf::CopyRect(*this, r);
}

template<typename T>
GLF_TYPES_INLINE Rect<T>::Rect(const point<T>& point, const size<T>& size)
{
	this->right = (this->left = point.x) + size.w;
	this->bottom = (this->top = point.y) + size.h;
}

template<typename T>
GLF_TYPES_INLINE Rect<T>::Rect(const point<T>& topLeft, const point<T>& bottomRight)
{ 
	this->left = topLeft.x;
	this->top = topLeft.y;
	this->right = bottomRight.x;
	this->bottom = bottomRight.y;
}

template<typename T>
GLF_TYPES_INLINE T Rect<T>::Width() const
{
	return this->right - this->left;
}

template<typename T>
GLF_TYPES_INLINE T Rect<T>::Height() const
{
	return this->bottom - this->top;
}

template<typename T>
GLF_TYPES_INLINE Point<T>& Rect<T>::TopLeft()
{
	return *((Point<T>*)&this->left);
}

template<typename T>
GLF_TYPES_INLINE Size<T> Rect<T>::Size() const
{
    return glf::Size<T>(this->right - this->left, this->bottom - this->top);
}




template<typename T>
GLF_TYPES_INLINE Point<T>& Rect<T>::BottomRight()
{
	return *((Point<T>*)&this->right);
}

template<typename T>
GLF_TYPES_INLINE const Point<T>& Rect<T>::TopLeft() const
{
	return *((Point<T>*)&this->left);
}

template<typename T>
GLF_TYPES_INLINE const Point<T>& Rect<T>::BottomRight() const
{
	return *((Point<T>*)&this->right);
}

template<typename T>
GLF_TYPES_INLINE Point<T> Rect<T>::CenterPoint() const
{
	return Point<T>((this->left+this->right)/2, (this->top+this->bottom)/2);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::SwapLeftRight()
{
    glf::SwapLeftRight(*this);
}
//
//template<typename T>
//GLF_TYPES_INLINE void Rect<T>::SwapLeftRight(LPRECT lpRect)
//{ LONG temp = r.left; r.left = r.right; r.right = temp; }

template<typename T>
GLF_TYPES_INLINE Rect<T>::operator rect<T>&()
{ 
	return *this;
}

//
//template<typename T>
//GLF_TYPES_INLINE Rect<T>::operator Rect<T>&() const
//{ 
//	return *this;
//}


template<typename T>
GLF_TYPES_INLINE bool Rect<T>::IsRectEmpty() const
{
    return glf::IsRectEmpty(*this);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::IsRectNull() const
{
	return (this->left == 0 && this->right == 0 && this->top == 0 && this->bottom == 0);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::PtInRect(const point<T>& point) const
{
    return glf::PtInRect(*this, point);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::SetRect(T x1, T y1, T x2, T y2)
{
	SetRect(*this, x1, y1, x2, y2);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::SetRect(const point<T>& topLeft, const point<T>& bottomRight)
{
	SetRect(*this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::SetRectEmpty()
{
    glf::SetRectEmpty(*this);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::CopyRect(const rect<T>& r)
{
	glf::CopyRect(*this, r);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::EqualRect(const rect<T>& r) const
{
	return glf::EqualRect(*this, r);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::InflateRect(T x, T y)
{
	InflateRect(*this, x, y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::InflateRect(const size<T>& size)
{
	InflateRect(*this, size.w, size.h);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::DeflateRect(T x, T y)
{
	InflateRect(*this, -x, -y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::DeflateRect(const size<T>& size)
{
	InflateRect(*this, -size.w, -size.h);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::OffsetRect(T x, T y)
{
	OffsetRect(*this, x, y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::OffsetRect(const point<T>& point)
{
	OffsetRect(*this, point.x, point.y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::OffsetRect(const size<T>& size)
{
	OffsetRect(*this, size.w, size.h);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::MoveToY(T y)
{
	this->bottom = Height() + y;
	this->top = y;
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::MoveToX(T x)
{
	this->right = Width() + x;
	this->left = x;
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::MoveToXY(T x, T y)
{
	MoveToX(x);
	MoveToY(y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::MoveToXY(const point<T>& pt)
{
	MoveToX(pt.x);
	MoveToY(pt.y);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::IntersectRect(const rect<T>& r1, const rect<T>& r2)
{
	return glf::IntersectRect(*this, r1, r2);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::UnionRect(const rect<T>& r1, const rect<T>& r2)
{
	return glf::UnionRect(*this, r1, r2);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator=(const rect<T>& srcRect)
{
	glf::CopyRect(*this, srcRect);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::operator==(const rect<T>& r) const
{
	return glf::EqualRect(*this, r);
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::operator!=(const rect<T>& r) const
{
	return !glf::EqualRect(*this, r);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator+=(const point<T>& point)
{
	OffsetRect(*this, point.x, point.y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator+=(const size<T>& size)
{
	OffsetRect(*this, size.w, size.h);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator+=(const rect<T>& r)
{
	InflateRect(r);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator-=(const point<T>& point)
{
	OffsetRect(*this, -point.x, -point.y);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator-=(const size<T>& size)
{
	OffsetRect(*this, -size.w, -size.h);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator-=(const rect<T>& r)
{
	DeflateRect(r);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator&=(const rect<T>& r)
{
	glf::IntersectRect(*this, *this, r);
}

template<typename T>
GLF_TYPES_INLINE void Rect<T>::operator|=(const rect<T>& r)
{
	glf::UnionRect(*this, *this, r);
}


template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator+(const point<T>& pt) const
{ 
	Rect<T> r(*this);
	OffsetRect(r, pt.x, pt.y);
	return r;
}


template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator-(const point<T>& pt) const
{ 
	Rect<T> r(*this);
	OffsetRect(r, -pt.x, -pt.y);
	return r;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator+(const size<T>& size) const
{
	Rect<T> r(*this);
	OffsetRect(r, size.w, size.h);
	return r;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator-(const size<T>& size) const
{ 
	Rect<T> r(*this);
	OffsetRect(r, -size.w, -size.h);
	return r;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator+(const rect<T>& r) const
{ 
	Rect r1(*this);
	r1.InflateRect(r);
	return r1;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator-(const rect<T>& r) const
{
	Rect rect(*this);
	rect.DeflateRect(r);
	return rect;
}


template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator&(const rect<T>& rect2) const
{ 
	Rect r;
	glf::IntersectRect(r, *this, rect2);
	return r;
}


template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::operator|(const rect<T>& rect2) const
{ 
	Rect rect;
	glf::UnionRect(rect, *this, rect2);
	return rect;
}

template<typename T>
GLF_TYPES_INLINE bool Rect<T>::SubtractRect(const rect<T>& r1, const rect<T>& r2)
{
	return glf::SubtractRect(*this, r1, r2);
}


template<typename T>
GLF_TYPES_INLINE void Rect<T>::NormalizeRect()
{
	T nTemp;
	if (this->left > this->right)
	{
		nTemp = this->left;
		this->left = this->right;
		this->right = nTemp;
	}
	if (this->top > this->bottom)
	{
		nTemp = this->top;
		this->top = this->bottom;
		this->bottom = nTemp;
	}
}


template<typename T>
GLF_TYPES_INLINE void Rect<T>::InflateRect(const rect<T>& r)
{
	this->left -= r.left;		
	this->top -= r.top;
	this->right += r.right;		
	this->bottom += r.bottom;
}


template<typename T>
GLF_TYPES_INLINE void Rect<T>::InflateRect(T l, T t, T r, T b)
{
	this->left -= l;			
	this->top -= t;
	this->right += r;			
	this->bottom += b;
}


template<typename T>
GLF_TYPES_INLINE void Rect<T>::DeflateRect(const rect<T>& r)
{
	this->left += r.left;
	this->top += r.top;
	this->right -= r.right;
	this->bottom -= r.bottom;
}


template<typename T>
GLF_TYPES_INLINE void Rect<T>::DeflateRect(T l, T t, T r, T b)
{
	this->left += l;
	this->top += t;
	this->right -= r;
	this->bottom -= b;
}

template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::Mul(T nMultiplier) const
{
	return Rect<T>(
		this->left * nMultiplier,
		this->top * nMultiplier,
		this->right * nMultiplier,
		this->bottom * nMultiplier);
}


template<typename T>
GLF_TYPES_INLINE Rect<T> Rect<T>::MulDiv(T nMultiplier, T nDivisor) const
{
	return Rect<T>(
		(this->left * nMultiplier) / nDivisor,
		(this->top * nMultiplier) / nDivisor,
		(this->right * nMultiplier) / nDivisor,
		(this->bottom * nMultiplier) / nDivisor);
}



} //namespace glf

#endif
